#ifndef __HASH_MAP_H__
#define __HASH_MAP_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>

#define LOG_ERROR printk
typedef char korp_mutex;

static inline uint8_t os_mutex_init(korp_mutex* lock)
{
   return true;
}

static inline uint8_t os_mutex_lock(korp_mutex* lock)
{
   return true;
}

static inline uint8_t os_mutex_unlock(korp_mutex* lock)
{
   return true;
}

static inline uint8_t os_mutex_destroy(korp_mutex* lock)
{
   return true;
}

/* 哈希映射的最小初始大小 */
#define HASH_MAP_MIN_SIZE 4

/* 哈希映射的最大初始大小 */
#define HASH_MAP_MAX_SIZE 65536

typedef uint32_t (*hash_func)(const void *key);

typedef bool (*key_equal_func)(void *key1, void *key2);

typedef void (*key_destroy_func)(void *key);

typedef void (*value_destroy_func)(void *value);

/* 遍历回调: 遍历每个哈希元素时自动调用 */
typedef void (*traverse_func_cb)(void *key, void *value, void *user_data);

typedef struct hash_map_elem {
   void* key;
   void* value;
   struct hash_map_elem* next;
} hash_map_elem;

typedef struct hash_map {
   /* 元素数组的大小 */
   uint32_t size;
   korp_mutex* lock;
   /* 哈希函数: 获取键的哈希值. */
   hash_func hash_func;
   /* 键检测: 检查两个键是否相等. */
   key_equal_func key_equal_func;
   /* 键删除: 删除指定键, 自动调用 */
   key_destroy_func key_destroy_func;
   /* 值删除: 删除指定值，自动调用 */
   value_destroy_func value_destroy_func;
   
   hash_map_elem* elements[1];   //默认偏移一个单位, 作为结构体包含该指针的大小
} hash_map;

/**
 * @brief 创建一个哈希表
 *
 * @param size 哈希映射的初始大小
 * @param use_lock 操作哈希映射时是否加锁
 *                  true: 加锁 , false: 不加锁
 * @param hash_func 哈希函数: 必须指定键
 * @param key_equal_func 键检测: 检查两个键是否相等
 * @param key_destroy_func 键删除: 删除指定键, 自动调用
 * @param value_destroy_func 值删除: 删除指定值，自动调用
 *
 * @return 成功: hash_map, 失败: NULL
 */
hash_map* bh_hash_map_create(uint32_t size, bool use_lock, hash_func hash_func,
                   key_equal_func key_equal_func, key_destroy_func key_destroy_func,
                   value_destroy_func value_destroy_func);

/**
 * @brief 向哈希映射插入一个元素
 *
 * @param map 插入元素的哈希映射
 * @param key 元素的键
 * @param value 元素的值
 *
 * @return 成功: true，失败: false
 * 注意: 如果key为NULL或hash map中存在重复key，则失败
 */
bool bh_hash_map_insert(hash_map* map, void* key, void* value);

/**
 * @brief 在哈希映射中查找一个元素
 *
 * @param map 查找元素的哈希映射
 * @param key 元素的键
 *
 * @return 成功: 查找元素的值, 失败: NULL
 */
void* bh_hash_map_find(hash_map* map, void* key);

/**
 * @brief 用新值更新哈希映射中的元素
 *
 * @param map 要更新元素的哈希映射
 * @param key 元素的键
 * @param value 元素的新值
 * @param p_old_value 如果不为NULL，则将旧值复制给它
 *
 * @return 成功: true, 失败: false
 * 注意: 旧的值不会被key_destroy_func销毁
 *       它将被复制到p_old_value中供用户处理。
 */
bool bh_hash_map_update(hash_map* map, void* key, void* value, void** p_old_value);

/**
 * @brief 从哈希映射中删除一个元素
 *
 * @param map 要删除元素的哈希映射
 * @param key 元素的键
 * @param p_old_key 如果不为NULL，则将旧键复制给它
 * @param p_old_value 如果不为NULL，则将旧值复制给它
 *
 * @return 成功: true, 失败: false
 * 注意: 旧键和旧值不会被销毁
 *       它们将被复制到p_old_key和p_old_value供用户处理。
 */
bool bh_hash_map_remove(hash_map* map, void* key, void** p_old_key,
                   void** p_old_value);

/**
 * @brief 销毁哈希映射
 *
 * @param map 要销毁的哈希映射
 *
 * @return 成功: true, 失败: false
 * 注意: 键销毁函数和值销毁函数将被调用来销毁
 *       每个元素的键和值(这个元素的键和值不为NULL)。
 */
bool bh_hash_map_destroy(hash_map* map);

/**
 * @brief 获取HashMap的结构大小
 *
 * @param map 要计算的哈希映射
 *
 * @return HashMap结构占用的内存空间
 */
uint32_t bh_hash_map_get_struct_size(hash_map* hashmap);

/**
 * @brief 获取HashMap元素的结构大小
 *
 * @return HashMap元素结构占用的内存空间
 */
uint32_t bh_hash_map_get_elem_struct_size(void);

/**
 * @brief 注册遍历哈希映射用的回调函数
 *
 * @param map 要遍历的哈希映射
 * @param callback 遍历回调函数
 * @param user_data 传递给回调函数的参数
 *
 * @return 成功: true, 失败: false
 * 注意: 如果哈希映射有锁，在遍历过程中该
 *       映射将被锁定, 应保持回调函数尽可能简单。
 */
bool bh_hash_map_traverse(hash_map* map, traverse_func_cb callback,
                     void* user_data);

#ifdef __cplusplus
}
#endif

#endif /* endof __HASH_MAP_H__ */
